/* 
 *  Copyright 2012 CodeMagi, Inc.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.codemagi.servlets.content.thumbnailers;

import com.codemagi.servlets.AppException;
import com.codemagi.servlets.BaseServlet;
import com.codemagi.servlets.content.ThumbnailController;
import com.codemagi.util.*;
import com.sun.media.jai.codec.FileSeekableStream;
import java.awt.Dimension;
import java.awt.Transparency;
import java.awt.image.ColorModel;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;
import java.io.IOException;
import javax.media.jai.*;
import javax.servlet.ServletContext;
import org.apache.log4j.Logger;

public class JAIThumbnailer implements com.codemagi.servlets.content.thumbnailers.IThumbnailer {

    Logger log = Logger.getLogger(this.getClass());

    //GETTERS AND SETTERS ------------------------

    public void setApplication(ServletContext newValue) {
	//no-op
    }

    public void createThumbnail(String sourceFile, String thumbFile, int targetWidth, int targetHeight, boolean doOverlay)
        throws AppException {

	String thumbDir = sourceFile.substring(0, sourceFile.lastIndexOf("/") + 1) + ThumbnailController.THUMBS_DIRECTORY + "/" ;

        log.debug("**** createThumbnail(" + sourceFile + ", " + thumbDir + ", " + thumbFile + ")");

	String extension = sourceFile.substring(sourceFile.lastIndexOf("."));

	log.debug("rendering for extension=" + extension);

	FileSeekableStream ss = null;

        try {
	    RenderedOp source         = null;
	    ss                        = new FileSeekableStream(sourceFile);
	    ParameterBlock loadParams = new ParameterBlock();
	    loadParams.add(ss);

	    if (".jpeg".equalsIgnoreCase(extension) || ".jpg".equalsIgnoreCase(extension)) {
		source = JAI.create("jpeg", loadParams);

		//JPEGs have inverse values on the K channel!    
		source = ThumbnailController.invertChannel(source, 3);

	    } else if (".tiff".equalsIgnoreCase(extension) || ".tif".equalsIgnoreCase(extension)) {
		source = JAI.create("tiff", loadParams);

	    } else if (".png".equalsIgnoreCase(extension)) {
		source = JAI.create("png", loadParams);

	    } else if (".gif".equalsIgnoreCase(extension)) {
		source = JAI.create("gif", loadParams);
		
		//force indexed color into RGB
		source = ThumbnailController.coerceRgb(source);

            } else {
		source = JAI.create("fileload", sourceFile);
	    }

	    log.debug("source="+source);
		
	    //provide info about source:
	    ThumbnailController.outputImageParams(source);

	    //Perform color and/or alpha channel conversions if needed
	    ColorModel cm = source.getColorModel();  
	    int numChannels  = cm.getNumComponents();
	    int bitsPerPixel = cm.getPixelSize();
	    if (".png".equalsIgnoreCase(extension) && cm.getTransparency() != Transparency.OPAQUE) {
		//strip the alpha channel
		source = ThumbnailController.stripAlphaChannel(source);
		
	    } else if ( cm.getNumComponents() == 4) {
		//convert cmyk to rgb
		source = ThumbnailController.convertCMYKtoRGB(source);
	    }


	    //scale the image
	    source = ThumbnailController.scaleImage(source, targetWidth, targetHeight);

	    //overlay a 'SAMPLE' watermark if this is not an official download
	    if (doOverlay) {
	    	source = ThumbnailController.overlayWatermark(source, source.getWidth(), source.getHeight());
	    }

	    //convert 16 bit color to 8 bit
	    if ( bitsPerPixel / numChannels == 16 ) {
		source = ThumbnailController.convert16BitTo8Bit(source);
	    }

	    //create the output directory if needed
            java.io.File outDir = new File(thumbDir);
            outDir.mkdirs();

	    com.sun.media.jai.codec.JPEGEncodeParam encodeParam = new com.sun.media.jai.codec.JPEGEncodeParam();
	    encodeParam.setQuality(ThumbnailController.THUMBNAIL_ENCODE_QUALITY);
	    if (!doOverlay) encodeParam.setQuality(ThumbnailController.DOWNLOAD_ENCODE_QUALITY);

	    //save the image to the filesystem
	    log.debug("ABOUT TO CREATE: source: " + source + " thumbFile: " + thumbFile);
	    JAI.create("filestore", source, thumbFile, "jpeg", encodeParam);

        } catch (Exception e) {
            log.debug("", e);
            throw new AppException(ThumbnailController.MSG_THUMBNAIL_ERROR);
        } catch (Throwable t) {
            log.debug("", t);
            throw new AppException(ThumbnailController.MSG_THUMBNAIL_ERROR);

        } finally {
	    BaseServlet.closeStream(ss);

	}
    }

    public Dimension getDimension(String sourceFile) throws AppException {

	RenderedOp image = null;
	try {
	    image = ImageUtils.loadImage(sourceFile);	
	} catch (IOException ioe) {
	    log.debug("IOEception in getDimension(" + sourceFile + ")");
	    throw new AppException("error loading image");
	}
	return new Dimension( image.getWidth(), image.getHeight() );
    }

}
